package cn.iocoder.yudao.module.indicator.util.index;


import cn.hutool.core.collection.CollectionUtil;
import cn.iocoder.yudao.module.indicator.base.IndexCalculationMap;
import cn.iocoder.yudao.module.indicator.domain.vo.ElementCalculationVo;
import cn.iocoder.yudao.module.indicator.domain.vo.IndexCalculationVo;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.stream.Collectors;

/**
 *@Description  指标计算工具类
 *@Author ZWC
 *@Date 2023/12/27 15:42
 */
@Component
public class IndexCalculationUtil {


    private IndexCalculationUtil() {}

    private static IndexCalculationUtil indexCalculationUtil;


    /**
     * 功能描述: 此方法根据元素计算指标值。确保每个元素id只有一条数据
     * @Param:
     * @Return:
     * @Author: ZWC
     * @Date: 2023/12/27
     */
    public static String getIndexValue(List<ElementCalculationVo> elementCalculationVoList, IndexCalculationVo indexCalculationVo){
        if (CollectionUtil.isNotEmpty(elementCalculationVoList)) {
            //执行指标值计算的入参
            IndexCalculationMap indexCalculationMap = new IndexCalculationMap();
            //根据元素id进行分组
            Map<Long, List<ElementCalculationVo>> groupByIdMap = elementCalculationVoList.stream().collect(Collectors.groupingBy(ElementCalculationVo::getId));
            //获取指标的计算公式
            String calculationFormulaId = indexCalculationVo.getCalculationFormulaId();
            //元素id数组
            List<Long> elementIdList = indexCalculationVo.getElementIdList();
            //如果获取不到元素则给元素赋值为0，维持指标的正常计算。
            for (Long elementId : elementIdList) {
                //给元素默认值0
                String elementNumber = "0";
                List<ElementCalculationVo> element = groupByIdMap.get(elementId);
                if (element != null) {
                    //分组后只会存在一条数据，能获取到说明元素值存在
                    elementNumber =  element.get(0).getElementNumber();
                }
                //放入指标计所需要的参数map
                indexCalculationMap.put(String.valueOf(elementId), elementNumber);
            }
            //只有一个元素则表示元素值既指标值，为了计算式子成立 `+0` 不影响结果且能够计算
            if(elementIdList.size() == 1 ) {
                calculationFormulaId = calculationFormulaId + "+0";
            }
            return Calculator.conversionToSting(calculationFormulaId, indexCalculationMap);
        }

        return "-";
    }

    /**
     * 获取指标科室的数据值
     * @param elementByData
     * @param indexCalculationVo
     * @return
     */
    public static ArrayList<ElementCalculationVo> getIndexDeptValue(List<ElementCalculationVo> elementByData, IndexCalculationVo indexCalculationVo){
        ArrayList<ElementCalculationVo> deptIndexList = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(elementByData)) {
            //按照机构进行分组
            Map<String, List<ElementCalculationVo>> stringListMap = elementByData.stream().
                    collect(Collectors.groupingBy(ElementCalculationVo::getGroupId));
            for (String s : stringListMap.keySet()) {
                List<ElementCalculationVo> elementCalculationVo= stringListMap.get(s);
                ElementCalculationVo elementCalculation = new ElementCalculationVo();
                elementCalculation.setElementNumber( getIndexValue(elementCalculationVo, indexCalculationVo));
                elementCalculation.setGroupId(s);
                elementCalculation.setGroupName(elementCalculationVo.get(0).getGroupName());
                deptIndexList.add(elementCalculation);
            }
        }
        return deptIndexList;
    }
    /**
     * 查询医生数据
     * @param elementDoctorList
     * @param indexCalculationVo
     * @return
     */
    public static ArrayList<ElementCalculationVo> getIndexDoctorValue(List<ElementCalculationVo> elementDoctorList, IndexCalculationVo indexCalculationVo){
        ArrayList<ElementCalculationVo> deptIndexList = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(elementDoctorList)) {
            //按照医生进行分组
            Map<String, List<ElementCalculationVo>> stringListMap = elementDoctorList.stream().
                    collect(Collectors.groupingBy(ElementCalculationVo::getGroupId));
            for (String doctorId : stringListMap.keySet()) {
                List<ElementCalculationVo> elementCalculationVo= stringListMap.get(doctorId);
                //创建明细指标对象并设置指标值
                ElementCalculationVo elementCalculation = new ElementCalculationVo();
                elementCalculation.setGroupId(doctorId);
                elementCalculation.setGroupName(elementCalculationVo.get(0).getGroupName());
                elementCalculation.setElementNumber( getIndexValue(elementCalculationVo, indexCalculationVo));
                deptIndexList.add(elementCalculation);
            }
        }
        return getIndexDeptValue(elementDoctorList, indexCalculationVo);
    }

    /**
     * 查询诊室数据
     * @param elementRoomList
     * @param indexCalculationVo
     * @return
     */
    public static ArrayList<ElementCalculationVo> getIndexRoomValue(List<ElementCalculationVo> elementRoomList, IndexCalculationVo indexCalculationVo){
        ArrayList<ElementCalculationVo> roomIndexList = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(elementRoomList)) {
            Map<String, List<ElementCalculationVo>> stringListMap = elementRoomList.stream().
                    collect(Collectors.groupingBy(ElementCalculationVo::getGroupId));
            for (String doctorId : stringListMap.keySet()) {
                List<ElementCalculationVo> elementCalculationVo= stringListMap.get(doctorId);
                //创建明细指标对象并设置指标值
                ElementCalculationVo elementCalculation = new ElementCalculationVo();
                elementCalculation.setGroupId(doctorId);
                elementCalculation.setGroupName(elementCalculationVo.get(0).getGroupName());
                elementCalculation.setElementNumber( getIndexValue(elementCalculationVo, indexCalculationVo));
                roomIndexList.add(elementCalculation);
            }
        }
        return getIndexDeptValue(roomIndexList, indexCalculationVo);
    }
        /**
         * sql调用元素表结果后，调用此方法进行处理查询出来的元素
         * @param elementCalculationVoList
         * @param indexCalculationVo
         * @return
         */
    public static ArrayList<ElementCalculationVo> getIndexTrend(List<ElementCalculationVo> elementCalculationVoList, IndexCalculationVo indexCalculationVo,List<String> dateList){
        ArrayList<ElementCalculationVo> trendList = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(elementCalculationVoList)) {
            //按照时间进行分组
            Map<String, List<ElementCalculationVo>> stringListMap = elementCalculationVoList.stream().
                    collect(Collectors.groupingBy(ElementCalculationVo::getPeriodTime));
            for (String date : dateList) {
                List<ElementCalculationVo> elementCalculationVo= stringListMap.get(date);
                String elementNumber = "0";
                if (elementCalculationVo != null) {
                    elementNumber = getIndexValue(elementCalculationVo, indexCalculationVo);
                }
                ElementCalculationVo elementCalculation = new ElementCalculationVo();
                elementCalculation.setElementNumber(elementNumber);
                elementCalculation.setPeriodTime(date);
                trendList.add(elementCalculation);
            }
        }
        return trendList;
    }
}
